package main.java.aplicacion;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import main.java.aplicacion.categorias.entidades.Categoria;
import main.java.aplicacion.categorias.excepciones.CategoriaError;
import main.java.aplicacion.juegos.entidades.Juego;
import main.java.aplicacion.juegos.entidades.Version;
import main.java.aplicacion.usuarios.entidades.Cliente;
import main.java.aplicacion.usuarios.entidades.Desarrollador;
import main.java.aplicacion.usuarios.entidades.Usuario;
import main.java.aplicacion.usuarios.excepciones.UsuarioError;
import main.java.datatypes.juegos.CompraJuegoVO;
import main.java.datatypes.juegos.JuegoVO;
import main.java.datatypes.juegos.VersionVO;
import main.java.datatypes.usuarios.UsuarioVO;

public class ManejadorSistema {
	private static ManejadorSistema instance = null;
	private List<Usuario> usuarios;
	private List<Juego> juegos;
	private List<Categoria> categorias;
	private int numeroComentarios;

	public static ManejadorSistema getInstance() {
		if (instance == null) {
			instance = new ManejadorSistema();
		}
		return instance;
	}

	private ManejadorSistema() {
		this.usuarios = new ArrayList<Usuario>();
		this.juegos = new ArrayList<Juego>();
		this.categorias = new ArrayList<Categoria>();
		this.numeroComentarios = 0;
	}

	public void ClearAllData() {
		this.usuarios = new ArrayList<Usuario>();
		this.juegos = new ArrayList<Juego>();
		this.categorias = new ArrayList<Categoria>();
		this.numeroComentarios = 0;
	}
	
	public int getNumeroComentarios(){
		return this.numeroComentarios;
	}
	public void setNumeroComentarios(){
		this.numeroComentarios++;
	}

	public void addUsuario(Usuario usuario) {
		usuarios.add(usuario);
	}

	public int addJuego(Juego juego) {
		juegos.add(juego);
		return juegos.size();
	}

	public void addCategoria(Categoria categoria) {
		categorias.add(categoria);
	}

	public void removeUsuario(Usuario usuario) {
		usuarios.remove(usuario);
	}

	public void removeJuego(Juego juego) {
		juegos.remove(juego);
	}

	public void removeCategoria(Categoria categoria) {
		categorias.remove(categoria);
	}

	public boolean memberUsuarioPorNick(String nick) {
		for (Usuario us : this.usuarios) {
			if (us.getNick().equals(nick))
				return true;
		}
		return false;
	}

	public boolean memberUsuarioPorMail(String mail) {
		for (Usuario us : this.usuarios) {
			if (us.getMail().equals(mail))
				return true;
		}
		return false;
	}

	public boolean memberJuego(Juego juego) {
		for (Juego j : this.juegos) {
			if (j.getNombre().equals(juego.getNombre()))
				return true;
		}
		return false;
	}

	public boolean memberJuego(String nombre) {
		for (Juego j : this.juegos) {
			if (j.getNombre().equals(nombre))
				return true;
		}
		return false;
	}

	public boolean memberCategoria(String categoria) {
		for (Categoria c : this.categorias) {
			if (c.getNombre().equals(categoria))
				return true;
		}
		return false;
		
		//Categoria c = this.findCategoria(categoria);
		//return (c == null);
	}

	public Usuario findUsuarioPorNick(String nick) {
		for (Usuario us : this.usuarios) {
			if (us.getNick().equals(nick))
				return us;
		}
		return null;
	}

	public Usuario findUsuarioPorMail(String mail) {
		for (Usuario us : this.usuarios) {
			if (us.getMail().equals(mail))
				return us;
		}
		return null;
	}

	public Juego findJuego(Juego juego) {
		for (Juego j : this.juegos) {
			if (j.getNombre().equals(juego.getNombre()))
				return j;
		}
		return null;
	}

	public Juego findJuego(String nombre) {
		for (Juego j : this.juegos) {
			if (j.getNombre().equals(nombre))
				return j;
		}
		return null;
	}

	public Categoria findCategoria(String categoria) {
		for (Categoria c : this.categorias) {
			if (c.getNombre().equals(categoria))
				return c;
		}
		return null;
	}
	
	public List<String> listarCategorias() throws ManejadorSistemaError{
		
		if(!this.categorias.isEmpty()){
			List<String> cat = new ArrayList<String>();
			ListIterator<Categoria> it = this.categorias.listIterator();
			while (it.hasNext()) {
				cat.add(((Categoria) it.next()).getNombre());
			}
			return cat;
		}
		else
			throw new ManejadorSistemaError(ManejadorSistemaError.TipoError.LISTA_CATEGORIAS_VACIA);
	}
	
	public List<String> listarJuegos() throws ManejadorSistemaError{
		
		if(!this.juegos.isEmpty()){
			List<String> j = new ArrayList<String>();
			for(Juego juegoActual: this.juegos){
				j.add(juegoActual.getNombre());
			}
			return j;
		}
		else
			throw new ManejadorSistemaError(ManejadorSistemaError.TipoError.LISTA_JUEGOS_VACIA);
	}
	
	public List<String> listarClientes() {
		
		List<Usuario> us = this.usuarios;
		List<String> clientes = new ArrayList<String>();
		ListIterator<Usuario> it = us.listIterator();
		while (it.hasNext()) {
			Usuario u = it.next();
			if (Cliente.class.isInstance(u)) {
				clientes.add(u.getNick());
			}
		}
		return (List<String>) clientes;
	}
	
	public List<UsuarioVO> listarUsuarios() {
		List<Usuario> us = this.usuarios;
		List<UsuarioVO> usuarios = new ArrayList<UsuarioVO>();
		for(Usuario usuario : us) {
			
			if (Desarrollador.class.isInstance(usuario)){
				UsuarioVO dtUsuario = ((Desarrollador)usuario).toDesarrolladorVO(); 
				usuarios.add(dtUsuario);
			}
			if (Cliente.class.isInstance(usuario)){
				UsuarioVO dtUsuario = ((Cliente)usuario).toClienteVO();
				usuarios.add(dtUsuario);
			}			
			
		}
		return  usuarios;
	}

	public List<String> listarDesarrolladores() throws ManejadorSistemaError {
		
		List<Usuario> us = this.usuarios;
		List<String> desarrolladores = new ArrayList<String>();
		ListIterator<Usuario> it = us.listIterator();
		while (it.hasNext()) {
			Usuario u = it.next();
			if (Desarrollador.class.isInstance(u)) {
				desarrolladores.add(u.getNick());
			}
		}
		if (desarrolladores.isEmpty())
			throw new ManejadorSistemaError(ManejadorSistemaError.TipoError.LISTA_DESARROLLADORES_VACIA);
		return desarrolladores;
	}

	public List<String> listarJuegosCategoria(String nom) throws ManejadorSistemaError, CategoriaError {
		Categoria cat = this.findCategoria(nom);
		if(cat != null){
			return  cat.listarJuegos();
		}
		else
			throw new CategoriaError(CategoriaError.TipoError.CATEGORIA_NO_EXISTE);
		/*if(!this.juegos.isEmpty()){
			List<String> j = new ArrayList<String>();
			for(Juego juegoActual: this.juegos){
				if (juegoActual.getNombre().equals(nom))
					j.add(juegoActual.getNombre());
			}
			return j;
		}
		else
			throw new ManejadorSistemaError(ManejadorSistemaError.TipoError.LISTA_JUEGOS_VACIA);*/
	}

	public boolean IsEmptyJuegos() {
		return this.juegos.isEmpty();
	}
	
	public List<CompraJuegoVO> listarDataCompra ()
	{
		List<CompraJuegoVO> list = new ArrayList<CompraJuegoVO>(); 
		for (Juego juegoActual: this.juegos){
			list.add(juegoActual.getCompraJuegoVO());			
		}
		return list;
	}
	
	public List<VersionVO> listarJuegosPendientes(){
		List<VersionVO> lv = new ArrayList<VersionVO>();
		for(Juego j: this.juegos){
			List<Version> vpj = j.getVersionesPendientes();
			if (!vpj.isEmpty()){
				for(Version v: vpj){
					lv.add(new VersionVO(v.getNumero(),j.getNombre(),j.getDesarrollador().getNick(),v.getDirVersion(),v.getTamanio(), v.getEstado().getNombre(), v.getEstado().getMotivo()));
				}
			}
		}
		return lv;
	}
	
	public List<String> listarJuegosAprobCategoria(String nom) throws ManejadorSistemaError, CategoriaError {
		List<String> juegosCat = this.listarJuegosCategoria(nom);
		List<String> juegosCatAp = new ArrayList<String>();
		for(String s: juegosCat)
		{
			if (this.findJuego(s).getUltAprobada()!= null)
				juegosCatAp.add(s);
			
		}
		return juegosCatAp;
	}
	
	
	public List<String> listarJuegosAprobadosDesarrollador(String nick) throws UsuarioError{
		Usuario d = this.findUsuarioPorNick(nick);
		if(!Desarrollador.class.isInstance(d)){
			throw new UsuarioError(UsuarioError.TipoError.USUARIO_INVALIDO);
		}
		else{
			List<Juego> juegosPublicados = ((Desarrollador) d).getJuegosPublicados();
			List<String>  juegos = new ArrayList<String>();
			if(juegosPublicados!=null){
				for(Juego j: juegosPublicados){
					if(j.getUltAprobada() != null){
						juegos.add(j.getNombre());
					}	
				}
			}
			return juegos;		
		}
	}	
	
	public List<String> listarJuegosPublicadosDesarrollador(String nick) throws UsuarioError{
		Usuario d = this.findUsuarioPorNick(nick);
		if(!Desarrollador.class.isInstance(d)){
			throw new UsuarioError(UsuarioError.TipoError.USUARIO_INVALIDO);
		}
		else{
			List<String> juego = new ArrayList<String>();
			for (Juego j : ((Desarrollador) d).getJuegosPublicados() ){
				juego.add(j.getNombre());
			}
			return juego;
		}
	}	
	
	public List<JuegoVO> listarJuegosVO(){
		List<JuegoVO> res = new ArrayList<JuegoVO>();
		for(Juego juego: this.juegos){
			if(juego.getUltAprobada() != null)	
				res.add(juego.getJuegoVO());
		}
		return res;
		
	}
	
	public List<String> obtenerCategorias(){
		List<String> res = new ArrayList<String>();
		for(Categoria cat : this.categorias){
			res.add(cat.getNombre());
		}
		return res;
	}
}